package cn.jiaqiang.chatgpt.data.domain.order.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.jiaqiang.chatgpt.data.domain.order.model.aggregates.CreateOrderAggregate;
import cn.jiaqiang.chatgpt.data.domain.order.model.entity.OrderEntity;
import cn.jiaqiang.chatgpt.data.domain.order.model.entity.PayOrderEntity;
import cn.jiaqiang.chatgpt.data.domain.order.model.entity.ProductEntity;
import cn.jiaqiang.chatgpt.data.domain.order.model.valobj.OrderStatusVO;
import cn.jiaqiang.chatgpt.data.domain.order.model.valobj.PayStatusVO;
import cn.jiaqiang.chatgpt.data.domain.order.model.valobj.PayTypeVO;
import cn.jiaqiang.chatgpt.data.types.weixinPay.PaySignUtil;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;



import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @description 订单服务
 */
@Slf4j
@Service
public class OrderService extends AbstractOrderService {

    @Value("${wxpay.config.appid}")
    private String appid;
    @Value("${wxpay.config.mchid}")
    private String mchid;
    @Value("${wxpay.config.notify-url}")
    private String notifyUrl;

    @Value("${personal.wxpay.mchId}")
    private String personalMchId;
    @Value("${personal.wxpay.key}")
    private String personalKey;
    @Value("${personal.wxpay.notifyUrl}")
    private String personalNotifyUrl;
    @Value("${personal.wxpay.url}")
    private String personalUrl;


    @Autowired(required = false)
    private NativePayService payService;

    @Override
    public OrderEntity doSaveOrder(String openid, ProductEntity productEntity) {
        OrderEntity orderEntity = new OrderEntity();
        // 雪花算法生成id
        orderEntity.setOrderId(String.valueOf(snowflakeIdGenerator.nextId()));
        orderEntity.setOrderTime(new Date()); // 下单时间
        orderEntity.setOrderStatus(OrderStatusVO.CREATE); // 订单状态: 创建完成
        orderEntity.setTotalAmount(productEntity.getPrice()); // 商品价格(订单金额)
        orderEntity.setPayTypeVO(PayTypeVO.WEIXIN_NATIVE); // 支付方式 -> 微信支付
        // 聚合信息(用户 + 商品 + 订单)
        CreateOrderAggregate aggregate = CreateOrderAggregate
                .builder()
                .openid(openid)
                .product(productEntity)
                .order(orderEntity)
                .build();
        // 保存订单；订单和支付，是2个操作。
        // 一个是数据库操作，一个是HTTP操作。所以不能一个事务处理，只能先保存订单再操作创建支付单，如果失败则需要任务补偿
        orderRepository.saveOrder(aggregate);
        return orderEntity;
    }

    /**
     * 生成支付单
     * @param openid 用户id
     * @param orderId 订单id
     * @param productName 产品名
     * @param amountTotal 金额
     * @return 支付单实体
     */
    @Override
    protected PayOrderEntity doPrepayOrder(String openid, String orderId, String productName, BigDecimal amountTotal) {
        // 构造微信支付请求 PrepayRequest
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        // 将一个 BigDecimal 类型的金额值乘以 100，然后转换为 int 类型并设置给 amount 的 total 属性。
        // 这种操作通常是为了将金额转换为以分为单位的整数值，以便在处理金额时避免精度丢失问题。
        amount.setTotal(amountTotal.multiply(new BigDecimal(100)).intValue());

        request.setAmount(amount); // 金额
        request.setDescription(productName); // 产品名
        request.setOutTradeNo(orderId); // 订单id
        request.setAppid(appid); // 申请支付主体的 appid
        request.setMchid(mchid); // 商户号
        request.setNotifyUrl(notifyUrl); // 回调地址

        // 创建微信支付单，如果你有多种支付方式，则可以根据支付类型的策略模式进行创建支付单
        String codeUrl ;
        if (null != payService) {
            // 发起微信支付
            PrepayResponse prepay = payService.prepay(request);
            // 获取支付二维码 url
            codeUrl = prepay.getCodeUrl();
        } else {
            codeUrl = "因你未配置支付渠道，所以暂时不能生成有效的支付URL。请配置支付渠道后，在application-dev.yml中配置支付渠道信息";
        }

        // 构造支付实体
        PayOrderEntity payOrderEntity = PayOrderEntity.builder()
                .openid(openid)
                .orderId(orderId)
                .payUrl(codeUrl)
                .payStatus(PayStatusVO.WAIT) // 等待支付
                .build();

        // 更新订单支付信息
        orderRepository.updateOrderPayInfo(payOrderEntity);
        return payOrderEntity;
    }


    /**
     * 蓝兔个人微信支付 - 生成微信支付单
     * @param openid 用户id
     * @param orderId 订单id
     * @param productName 产品名
     * @param amountTotal 金额
     * @return 支付单实体
     */
    @Override
    protected PayOrderEntity doPersonalPrepayOrder(String openid, String orderId, String productName, String amountTotal) {
        //当前时间戳
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

        Map<String, Object> map = new HashMap<>();
        map.put("mch_id", personalMchId);
        map.put("out_trade_no", orderId);
        map.put("total_fee", amountTotal);
        map.put("body", productName);
        map.put("notify_url", personalNotifyUrl);
        map.put("timestamp", timestamp);
        String sign = PaySignUtil.createSign(map, personalKey);
        map.put("sign", sign);
        String result = HttpRequest.post(personalUrl)
                .form(map)
                .execute()
                .body();
        String msg = "";
        if (StrUtil.isBlank(result)) {
            msg = "API接口返回为空，请联系客服";
        } else {
            try {
                JSONObject jsonObject = (JSONObject)JSONObject.parse(result);
                Integer code = jsonObject.getInteger("code");
                if(code == 0){
                    String qrcode = jsonObject.getJSONObject("data").getString("QRcode_url");
                    msg = "请使用微信扫码下方二维码:" + qrcode;
                    // 构造支付实体
                    PayOrderEntity payOrderEntity = PayOrderEntity.builder()
                            .openid(openid)
                            .orderId(orderId)
                            .payUrl(qrcode)
                            .payStatus(PayStatusVO.WAIT) // 等待支付
                            .build();
                    // 更新订单支付信息
                    orderRepository.updateOrderPayInfo(payOrderEntity);
                    return payOrderEntity;
                } else {
                    String msgStr = jsonObject.getString("msg");
                    msg = "返回失败：" + msgStr;
                }
            } catch (Exception e) {
                log.error("生成支付单出错: ", e);
            }
        }
        log.info(msg);
        return null;
    }

    /**
     * 变更: 订单支付成功
     * @param orderId 订单id
     * @param transactionId 交易单号
     * @param totalAmount 总金额
     * @param payTime 支付时间
     */
    @Override
    public boolean changeOrderPaySuccess(String orderId, String transactionId, BigDecimal totalAmount, Date payTime) {
        return orderRepository.changeOrderPaySuccess(orderId, transactionId, totalAmount, payTime);
    }

    @Override
    public CreateOrderAggregate queryOrder(String orderId) {
        return orderRepository.queryOrder(orderId);
    }

    /**
     * 订单商品发货
     *
     * @param orderId 订单ID
     */
    @Override
    public void deliverGoods(String orderId) {
       orderRepository.deliverGoods(orderId);
    }

    /**
     * 查询待补货订单
     */
    @Override
    public List<String> queryReplenishmentOrder() {
        return orderRepository.queryReplenishmentOrder();
    }

    @Override
    public List<String> queryNoPayNotifyOrder() {
        return orderRepository.queryNoPayNotifyOrder();
    }

    /**
     * 查询超时15分钟，未支付订单
     */
    @Override
    public List<String> queryTimeoutCloseOrderList() {
        return orderRepository.queryTimeoutCloseOrderList();
    }

    /**
     * 变更；订单支付关闭
     */
    @Override
    public boolean changeOrderClose(String orderId) {
        return orderRepository.changeOrderClose(orderId);
    }

    @Override
    public List<ProductEntity> queryProductList() {
        return orderRepository.queryProductList();
    }

}
